#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
多格式视频转换工具 - 图形用户界面
"""

import os
import sys
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from pathlib import Path
import threading
import queue
from typing import List, Optional
import logging

# 导入转换功能
from webm_to_mp4 import convert_video, batch_convert, check_ffmpeg, SUPPORTED_INPUT_FORMATS

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 莫兰迪色系
COLORS = {
    "bg": "#F5F5F5",
    "frame_bg": "#F0F0F0",
    "accent1": "#A6C0BC",  # 莫兰迪青绿色
    "accent2": "#E6D2CA",  # 莫兰迪粉橙色
    "accent3": "#D2D5DB",  # 莫兰迪浅灰蓝
    "accent4": "#BFD6DD",  # 莫兰迪浅蓝色
    "text": "#555555",
    "btn_bg": "#A6C0BC",
    "btn_hover": "#8FB0AB",
    "btn_active": "#7DA19B",
    "btn_fg": "#FFFFFF",
}

# 支持的输出格式
OUTPUT_FORMATS = ["mp4", "avi", "mkv", "mov", "webm"]

class VideoConverterGUI(tk.Tk):
    """多格式视频转换工具的图形用户界面"""
    
    def __init__(self):
        """初始化应用程序"""
        super().__init__()
        
        self.title("愿序视频转换工具 Powered by BensonZhag")
        self.geometry("750x650")  # 调整窗口高度
        self.minsize(650, 500)  # 调整最小高度
        self.configure(bg=COLORS["bg"])
        
        # 设置应用程序图标
        # self.iconbitmap("icon.ico")  # 如有图标可取消注释
        
        # 创建消息队列，用于线程间通信
        self.queue = queue.Queue()
        
        # 正在转换的标志
        self.converting = False
        
        # 创建自定义样式
        self._create_styles()
        
        # 预先创建共享变量
        self._create_shared_variables()
        
        # 创建界面
        self._create_widgets()
        self._create_layout()
        self._setup_bindings()
        
        # 启动周期性检查消息队列
        self.after(100, self._process_queue)
        
        # 验证FFmpeg是否已安装
        if not check_ffmpeg():
            messagebox.showerror("错误", "未检测到FFmpeg。请安装FFmpeg并确保它在系统路径中。")
    
    def _create_styles(self):
        """创建自定义样式"""
        self.style = ttk.Style(self)
        
        # 配置全局样式
        self.style.configure('TFrame', background=COLORS["frame_bg"])
        self.style.configure('TLabelframe', background=COLORS["frame_bg"])
        self.style.configure('TLabelframe.Label', background=COLORS["frame_bg"], foreground=COLORS["text"])
        self.style.configure('TLabel', background=COLORS["frame_bg"], foreground=COLORS["text"])
        self.style.configure('TCheckbutton', background=COLORS["frame_bg"], foreground=COLORS["text"])
        self.style.configure('TEntry', fieldbackground=COLORS["bg"])
        self.style.configure('TCombobox', fieldbackground=COLORS["bg"])
        
        # 配置按钮样式
        self.style.configure('Accent.TButton', 
                             background=COLORS["btn_bg"], 
                             foreground="#000080",  # 深蓝色字体
                             font=('微软雅黑', 10, 'bold'))
        self.style.map('Accent.TButton',
                       background=[('active', COLORS["btn_active"]), 
                                  ('hover', COLORS["btn_hover"])],
                       foreground=[('active', "#000080"),  # 保持深蓝色
                                  ('hover', "#000080")])
        
        # 停止按钮样式
        self.style.configure('Stop.TButton', 
                             background="#E74C3C",  # 红色背景 
                             foreground="#FF0000",  # 红色字体
                             font=('微软雅黑', 9, 'bold'))
        self.style.map('Stop.TButton',
                       background=[('active', "#C0392B"), 
                                  ('hover', "#D35400")],
                       foreground=[('active', "#FF0000"),
                                  ('hover', "#FF0000")])
        
        # 配置选项卡样式
        self.style.configure('TNotebook', background=COLORS["bg"], tabmargins=[2, 5, 2, 0])
        self.style.configure('TNotebook.Tab', 
                             background=COLORS["accent3"], 
                             foreground=COLORS["text"],
                             padding=[10, 2], 
                             font=('微软雅黑', 9))
        self.style.map('TNotebook.Tab',
                      background=[('selected', COLORS["accent1"])],
                      foreground=[('selected', COLORS["text"])])  # 修改选中标签页的字体颜色
        
        # 配置进度条样式
        self.style.configure('TProgressbar', 
                             background=COLORS["accent1"],
                             troughcolor=COLORS["frame_bg"])
    
    def _create_shared_variables(self):
        """预先创建共享的变量，供不同标签页使用"""
        # 视频编码器变量
        self.video_codec_var = tk.StringVar(value="libx264")
        
        # 音频编码器变量
        self.audio_codec_var = tk.StringVar(value="aac")
        
        # 视频比特率变量
        self.video_bitrate_var = tk.StringVar()
        
        # 音频比特率变量
        self.audio_bitrate_var = tk.StringVar(value="192k")
        
        # 硬件加速选项
        self.hw_accel_var = tk.StringVar(value="")
        
        # 速度预设
        self.speed_preset_var = tk.StringVar(value="medium")
        
        # 并行任务数
        self.max_workers_var = tk.StringVar(value="")
        
        # 检测可用的硬件加速选项
        self.available_hw_accel = self._detect_hw_accel()
    
    def _create_widgets(self):
        """创建界面组件"""
        # 选项卡控件
        self.notebook = ttk.Notebook(self)
        
        # 各种格式转换选项卡
        self.tabs = {}
        self.format_frames = {}
        for output_format in OUTPUT_FORMATS:
            frame = ttk.Frame(self.notebook, padding="10")
            tab_name = f"{output_format.upper()}转换"
            self.notebook.add(frame, text=tab_name)
            self.tabs[output_format] = frame
            self.format_frames[output_format] = self._create_format_frame(frame, output_format)
        
        # 批量转换选项卡
        self.batch_frame = ttk.Frame(self.notebook, padding="10")
        self.notebook.add(self.batch_frame, text="批量转换")
        
        # === 批量转换选项卡 ===
        # 输入目录
        self.batch_input_frame = ttk.LabelFrame(self.batch_frame, text="输入目录", padding="5")
        self.batch_input_var = tk.StringVar()
        self.batch_input_entry = ttk.Entry(self.batch_input_frame, textvariable=self.batch_input_var, width=50)
        self.batch_input_button = ttk.Button(self.batch_input_frame, text="浏览...", command=self._browse_input_dir)
        
        # 输出目录
        self.batch_output_frame = ttk.LabelFrame(self.batch_frame, text="输出目录", padding="5")
        self.batch_output_var = tk.StringVar()
        self.batch_output_entry = ttk.Entry(self.batch_output_frame, textvariable=self.batch_output_var, width=50)
        self.batch_output_button = ttk.Button(self.batch_output_frame, text="浏览...", command=self._browse_output_dir)
        
        # 文件格式选择
        self.batch_format_frame = ttk.LabelFrame(self.batch_frame, text="文件格式", padding="5")
        
        # 输入格式多选框
        self.input_format_label = ttk.Label(self.batch_format_frame, text="输入格式:")
        self.input_format_vars = {}
        self.input_format_checks = {}
        
        # 创建输入格式复选框
        self.input_formats_frame = ttk.Frame(self.batch_format_frame)
        row, col = 0, 0
        for fmt in [ext.strip('.') for ext in SUPPORTED_INPUT_FORMATS]:
            var = tk.BooleanVar(value=True)
            check = ttk.Checkbutton(self.input_formats_frame, text=fmt, variable=var)
            check.grid(row=row, column=col, sticky="w", padx=5, pady=2)
            self.input_format_vars[fmt] = var
            self.input_format_checks[fmt] = check
            col += 1
            if col > 3:  # 每行显示4个复选框
                col = 0
                row += 1
        
        # 输出格式选择
        self.output_format_label = ttk.Label(self.batch_format_frame, text="输出格式:")
        self.output_format_var = tk.StringVar(value="mp4")
        self.output_format_combo = ttk.Combobox(self.batch_format_frame, textvariable=self.output_format_var, width=15)
        self.output_format_combo['values'] = OUTPUT_FORMATS
        self.output_format_combo.state(['readonly'])
        
        # 递归处理选项 - 移到文件格式框架中
        self.recursive_var = tk.BooleanVar(value=False)
        self.recursive_check = ttk.Checkbutton(
            self.batch_format_frame, 
            text="递归处理子目录", 
            variable=self.recursive_var
        )
        
        # 批量转换选项
        self.batch_options_frame = ttk.LabelFrame(self.batch_frame, text="转换选项", padding="5")
        
        # 批量转换按钮 - 这个按钮不再使用，改用全局按钮
        self.batch_convert_button = ttk.Button(
            self.batch_frame, 
            text="开始批量转换", 
            command=self._start_batch_conversion,
            style='Accent.TButton'
        )
        
        # 批量停止按钮 - 完全不使用
        self.batch_stop_button = ttk.Button(
            self.batch_frame,
            text="停止转换",
            command=self._stop_conversion,
            style='Stop.TButton'
        )
        
        # 日志区域
        self.log_frame = ttk.LabelFrame(self, text="转换日志", padding="5")
        self.log_text = tk.Text(self.log_frame, wrap=tk.WORD, width=80, height=8,  # 保持用户修改的高度
                                bg=COLORS["bg"], fg=COLORS["text"])
        self.log_scroll = ttk.Scrollbar(self.log_frame, orient="vertical", command=self.log_text.yview)
        self.log_text.configure(yscrollcommand=self.log_scroll.set)
        
        # 进度条和停止按钮容器
        self.progress_frame = ttk.Frame(self)
        
        # 停止按钮 - 只使用这一个停止按钮
        self.stop_button = ttk.Button(
            self.progress_frame,
            text="停止转换",
            command=self._stop_conversion,
            style='Stop.TButton'
        )
        
        # 进度条
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(
            self.progress_frame, 
            orient="horizontal", 
            length=400,
            mode="determinate", 
            variable=self.progress_var
        )
        
        # 进度标签
        self.progress_label = ttk.Label(
            self.progress_frame,
            text="0%",
            background=COLORS["bg"],
            foreground=COLORS["text"]
        )
        
        # 状态栏框架
        self.status_frame = ttk.Frame(self)
        
        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        self.status_label = ttk.Label(self, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
    
    def _create_format_frame(self, parent, output_format):
        """为每种输出格式创建转换界面"""
        frame_data = {}
        
        # 输入文件
        input_frame = ttk.LabelFrame(parent, text="输入文件", padding="5")
        input_var = tk.StringVar()
        input_entry = ttk.Entry(input_frame, textvariable=input_var, width=50)
        input_button = ttk.Button(
            input_frame, 
            text="浏览...", 
            command=lambda: self._browse_input_file(input_var, output_format)
        )
        
        # 输出文件
        output_frame = ttk.LabelFrame(parent, text="输出文件", padding="5")
        output_var = tk.StringVar()
        output_entry = ttk.Entry(output_frame, textvariable=output_var, width=50)
        output_button = ttk.Button(
            output_frame, 
            text="浏览...", 
            command=lambda: self._browse_output_file(output_var, output_format)
        )
        
        # 转换选项
        options_frame = ttk.LabelFrame(parent, text="转换选项", padding="5")
        
        # 转换按钮
        convert_button = ttk.Button(
            parent, 
            text=f"开始转换为{output_format.upper()}", 
            command=lambda: self._start_single_conversion(input_var, output_var, output_format),
            style='Accent.TButton'
        )
        
        # 保存组件引用
        frame_data["input_frame"] = input_frame
        frame_data["input_var"] = input_var
        frame_data["input_entry"] = input_entry
        frame_data["input_button"] = input_button
        frame_data["output_frame"] = output_frame
        frame_data["output_var"] = output_var
        frame_data["output_entry"] = output_entry
        frame_data["output_button"] = output_button
        frame_data["options_frame"] = options_frame
        frame_data["convert_button"] = convert_button
        
        # 布局组件
        input_frame.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        input_frame.columnconfigure(0, weight=1)
        input_entry.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        input_button.grid(row=0, column=1, sticky="e", padx=5, pady=5)
        
        output_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=5)
        output_frame.columnconfigure(0, weight=1)
        output_entry.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        output_button.grid(row=0, column=1, sticky="e", padx=5, pady=5)
        
        options_frame.grid(row=2, column=0, sticky="ew", padx=5, pady=5)
        options_frame.columnconfigure(1, weight=1)
        options_frame.columnconfigure(3, weight=1)
        
        # 为每种输出格式配置推荐编码器
        # 创建当前格式的编码器选项变量
        format_video_codec_var = tk.StringVar()
        format_audio_codec_var = tk.StringVar()
        format_video_bitrate_var = tk.StringVar()
        format_audio_bitrate_var = tk.StringVar(value="192k")
        format_hw_accel_var = tk.StringVar(value="")
        format_speed_preset_var = tk.StringVar(value="medium")
        
        # 设置默认推荐编码器
        if output_format.lower() == "mp4":
            format_video_codec_var.set("libx264")
            format_audio_codec_var.set("aac")
        elif output_format.lower() == "avi":
            format_video_codec_var.set("mpeg4")
            format_audio_codec_var.set("mp3")
        elif output_format.lower() == "mkv":
            format_video_codec_var.set("libx264")
            format_audio_codec_var.set("aac")
        elif output_format.lower() == "mov":
            format_video_codec_var.set("libx264")
            format_audio_codec_var.set("aac")
        elif output_format.lower() == "webm":
            format_video_codec_var.set("libvpx-vp9")
            format_audio_codec_var.set("libopus")
        
        # 保存格式特定的变量引用
        frame_data["format_video_codec_var"] = format_video_codec_var
        frame_data["format_audio_codec_var"] = format_audio_codec_var
        frame_data["format_video_bitrate_var"] = format_video_bitrate_var
        frame_data["format_audio_bitrate_var"] = format_audio_bitrate_var
        frame_data["format_hw_accel_var"] = format_hw_accel_var
        frame_data["format_speed_preset_var"] = format_speed_preset_var
        
        # 第一行选项 - 视频编码器和音频编码器
        ttk.Label(options_frame, text="视频编码器:").grid(row=0, column=0, sticky="w", padx=5, pady=5)
        
        # 为不同格式提供不同的编码器选项
        video_codec_options = []
        if output_format.lower() == "webm":
            video_codec_options = ['libvpx-vp9', 'libvpx', 'copy']
        elif output_format.lower() == "avi":
            video_codec_options = ['mpeg4', 'msmpeg4', 'libxvid', 'copy']
        elif output_format.lower() == "mkv":
            video_codec_options = ['libx264', 'libx265', 'copy']
        elif output_format.lower() == "mov":
            video_codec_options = ['libx264', 'prores', 'copy']
        else:  # mp4
            video_codec_options = ['libx264', 'libx265', 'copy']
        
        video_codec_combo = ttk.Combobox(options_frame, textvariable=format_video_codec_var, width=15)
        video_codec_combo['values'] = video_codec_options
        video_codec_combo.state(['readonly'])
        video_codec_combo.grid(row=0, column=1, sticky="w", padx=5, pady=5)
        
        # 视频编码器说明
        video_codec_help = ttk.Label(options_frame, text="?", foreground="blue", cursor="hand2")
        video_codec_help.grid(row=0, column=1, sticky="e", padx=(0, 10), pady=5)
        
        # 为不同格式提供不同的编码器说明
        if output_format.lower() == "webm":
            tooltip_text = "视频编码器选项说明:\n"\
                         "libvpx-vp9: VP9编码器，高压缩率，WebM推荐\n"\
                         "libvpx: VP8编码器，较旧的WebM编码器\n"\
                         "copy: 直接复制视频流，不重新编码，速度最快"
        elif output_format.lower() == "avi":
            tooltip_text = "视频编码器选项说明:\n"\
                         "mpeg4: MPEG-4编码，AVI推荐\n"\
                         "msmpeg4: 微软MPEG-4编码，兼容老旧设备\n"\
                         "libxvid: Xvid编码，开源、高效的MPEG-4编码\n"\
                         "copy: 直接复制视频流，不重新编码，速度最快"
        elif output_format.lower() == "mkv":
            tooltip_text = "视频编码器选项说明:\n"\
                         "libx264: H.264编码，MKV推荐，兼容性最好\n"\
                         "libx265: H.265/HEVC编码，更高压缩率\n"\
                         "copy: 直接复制视频流，不重新编码，速度最快"
        elif output_format.lower() == "mov":
            tooltip_text = "视频编码器选项说明:\n"\
                         "libx264: H.264编码，MOV推荐，兼容性最好\n"\
                         "prores: Apple ProRes编码，专业视频编辑\n"\
                         "copy: 直接复制视频流，不重新编码，速度最快"
        else:  # mp4
            tooltip_text = "视频编码器选项说明:\n"\
                         "libx264: H.264编码，MP4推荐，兼容性最好\n"\
                         "libx265: H.265/HEVC编码，更高压缩率但兼容性较差\n"\
                         "copy: 直接复制视频流，不重新编码，速度最快"
                         
        self._create_tooltip(video_codec_help, tooltip_text)
        
        ttk.Label(options_frame, text="音频编码器:").grid(row=0, column=2, sticky="w", padx=5, pady=5)
        
        # 为不同格式提供不同的音频编码器选项
        audio_codec_options = []
        if output_format.lower() == "webm":
            audio_codec_options = ['libopus', 'libvorbis', 'copy']
        elif output_format.lower() == "avi":
            audio_codec_options = ['mp3', 'ac3', 'copy']
        elif output_format.lower() == "mkv":
            audio_codec_options = ['aac', 'ac3', 'dts', 'copy']
        elif output_format.lower() == "mov":
            audio_codec_options = ['aac', 'alac', 'pcm_s16le', 'copy']
        else:  # mp4
            audio_codec_options = ['aac', 'mp3', 'copy']
        
        audio_codec_combo = ttk.Combobox(options_frame, textvariable=format_audio_codec_var, width=15)
        audio_codec_combo['values'] = audio_codec_options
        audio_codec_combo.state(['readonly'])
        audio_codec_combo.grid(row=0, column=3, sticky="w", padx=5, pady=5)
        
        # 音频编码器说明
        audio_codec_help = ttk.Label(options_frame, text="?", foreground="blue", cursor="hand2")
        audio_codec_help.grid(row=0, column=3, sticky="e", padx=(0, 10), pady=5)
        
        # 为不同格式提供不同的音频编码器说明
        if output_format.lower() == "webm":
            tooltip_text = "音频编码器选项说明:\n"\
                         "libopus: Opus编码，WebM推荐，高质量、低比特率\n"\
                         "libvorbis: Vorbis编码，较旧的WebM音频编码器\n"\
                         "copy: 直接复制音频流，不重新编码，速度最快"
        elif output_format.lower() == "avi":
            tooltip_text = "音频编码器选项说明:\n"\
                         "mp3: MP3编码，AVI推荐，普遍兼容\n"\
                         "ac3: AC3编码，高质量环绕声\n"\
                         "copy: 直接复制音频流，不重新编码，速度最快"
        elif output_format.lower() == "mkv":
            tooltip_text = "音频编码器选项说明:\n"\
                         "aac: AAC编码，MKV推荐，高质量、低比特率\n"\
                         "ac3: AC3编码，杜比数字环绕声\n"\
                         "dts: DTS编码，高保真环绕声\n"\
                         "copy: 直接复制音频流，不重新编码，速度最快"
        elif output_format.lower() == "mov":
            tooltip_text = "音频编码器选项说明:\n"\
                         "aac: AAC编码，MOV推荐，普遍兼容\n"\
                         "alac: Apple无损音频编码\n"\
                         "pcm_s16le: 未压缩PCM音频，最高质量\n"\
                         "copy: 直接复制音频流，不重新编码，速度最快"
        else:  # mp4
            tooltip_text = "音频编码器选项说明:\n"\
                         "aac: 高质量音频编码，MP4推荐，适用于大多数场景\n"\
                         "mp3: 常用音频格式，兼容性好\n"\
                         "copy: 直接复制音频流，不重新编码，速度最快"
        
        self._create_tooltip(audio_codec_help, tooltip_text)
        
        # 硬件加速选项
        hw_accel_label = ttk.Label(options_frame, text="硬件加速:")
        hw_accel_combo = ttk.Combobox(options_frame, textvariable=format_hw_accel_var, width=15)
        
        # 设置可用的硬件加速选项
        hw_accel_options = ['']  # 空选项表示不使用硬件加速
        hw_accel_options.extend([k for k, v in self.available_hw_accel.items() if v])
        hw_accel_combo['values'] = hw_accel_options
        hw_accel_combo.state(['readonly'])
        
        # 硬件加速说明
        hw_accel_help = ttk.Label(options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(hw_accel_help, 
                           "硬件加速选项说明:\n"
                           "空白: 不使用硬件加速\n"
                           "nvidia: 使用NVIDIA GPU加速\n"
                           "amd: 使用AMD GPU加速\n"
                           "intel: 使用Intel Quick Sync加速\n"
                           "apple: 使用Apple VideoToolbox加速")
        
        # 速度预设
        speed_preset_label = ttk.Label(options_frame, text="速度预设:")
        speed_preset_combo = ttk.Combobox(options_frame, textvariable=format_speed_preset_var, width=15)
        speed_preset_combo['values'] = ('ultrafast', 'veryfast', 'fast', 'medium', 'slow', 'veryslow')
        speed_preset_combo.state(['readonly'])
        
        # 速度预设说明
        speed_preset_help = ttk.Label(options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(speed_preset_help, 
                           "速度预设选项说明:\n"
                           "ultrafast: 极速转换，质量最低\n"
                           "veryfast: 非常快，质量较低\n"
                           "fast: 快速，质量较好\n"
                           "medium: 中等速度和质量(默认)\n"
                           "slow: 慢速，高质量\n"
                           "veryslow: 非常慢，最高质量")
        
        # 第二行选项 - 视频比特率和音频比特率
        video_bitrate_label = ttk.Label(options_frame, text="视频比特率:")
        video_bitrate_entry = ttk.Entry(options_frame, textvariable=format_video_bitrate_var, width=15)
        
        # 视频比特率说明
        video_bitrate_help = ttk.Label(options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(video_bitrate_help, 
                           "视频比特率建议值:\n"
                           "720p: 2000k-4000k\n"
                           "1080p: 4000k-8000k\n"
                           "4K: 15000k-30000k\n"
                           "留空则使用质量控制模式(CRF)")
        
        audio_bitrate_label = ttk.Label(options_frame, text="音频比特率:")
        audio_bitrate_entry = ttk.Entry(options_frame, textvariable=format_audio_bitrate_var, width=15)
        
        # 音频比特率说明
        audio_bitrate_help = ttk.Label(options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(audio_bitrate_help, 
                           "音频比特率建议值:\n"
                           "普通质量: 128k\n"
                           "标准质量: 192k (默认)\n"
                           "高质量: 256k-320k")
        
        # 布局 - 调整为更紧凑的布局
        # 硬件加速和速度预设
        hw_accel_label.grid(row=1, column=0, sticky="w", padx=5, pady=2)
        hw_accel_combo.grid(row=1, column=1, sticky="w", padx=5, pady=2)
        hw_accel_help.grid(row=1, column=1, sticky="e", padx=(0, 10), pady=2)
        
        speed_preset_label.grid(row=1, column=2, sticky="w", padx=5, pady=2)
        speed_preset_combo.grid(row=1, column=3, sticky="w", padx=5, pady=2)
        speed_preset_help.grid(row=1, column=3, sticky="e", padx=(0, 10), pady=2)
        
        # 视频比特率和音频比特率
        video_bitrate_label.grid(row=2, column=0, sticky="w", padx=5, pady=2)
        video_bitrate_entry.grid(row=2, column=1, sticky="w", padx=5, pady=2)
        video_bitrate_help.grid(row=2, column=1, sticky="e", padx=(0, 10), pady=2)
        
        audio_bitrate_label.grid(row=2, column=2, sticky="w", padx=5, pady=2)
        audio_bitrate_entry.grid(row=2, column=3, sticky="w", padx=5, pady=2)
        audio_bitrate_help.grid(row=2, column=3, sticky="e", padx=(0, 10), pady=2)
        
        # 如果是WebM格式，添加提示信息
        if output_format.lower() == "webm":
            info_frame = ttk.Frame(parent)
            info_frame.grid(row=3, column=0, sticky="ew", padx=5, pady=0)
            info_label = ttk.Label(
                info_frame, 
                text="注意: WebM格式需要使用特定编码器(VP8/VP9和Vorbis/Opus)才能正常转换",
                foreground="#E74C3C"
            )
            info_label.pack(pady=2)
        
        # 为每种格式添加支持文件信息
        info_frame = ttk.Frame(parent)
        info_frame.grid(row=4 if output_format.lower() == "webm" else 3, column=0, sticky="ew", padx=5, pady=0)
        info_label = ttk.Label(
            info_frame, 
            text=f"支持从任何格式转换为{output_format.upper()}格式",
            foreground="#2980B9"
        )
        info_label.pack(pady=2)
        
        # 转换按钮
        convert_button.grid(row=5 if output_format.lower() == "webm" else 4, column=0, sticky="ew", padx=5, pady=10)
        
        # 配置列权重
        parent.columnconfigure(0, weight=1)
        
        return frame_data
    
    def _create_layout(self):
        """布局界面组件"""
        # 配置主窗口网格
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)  # 选项卡
        self.rowconfigure(1, weight=0)  # 全局转换按钮区域
        self.rowconfigure(2, weight=0)  # 进度条和控制按钮
        self.rowconfigure(3, weight=2)  # 日志 - 保持合适的权重比例
        self.rowconfigure(4, weight=0)  # 状态栏
        
        # 放置选项卡控件
        self.notebook.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)
        
        # 放置全局转换按钮区域 - 只包含批量转换按钮，居中显示
        global_btn_frame = ttk.Frame(self)
        global_btn_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=2)
        
        # 将批量转换按钮重新创建在主界面全局区域 - 居中显示
        self.global_batch_convert_button = ttk.Button(
            global_btn_frame, 
            text="开始批量转换", 
            command=self._start_batch_conversion,
            style='Accent.TButton'
        )
        # 配置按钮居中
        global_btn_frame.columnconfigure(0, weight=1)
        global_btn_frame.columnconfigure(1, weight=1)
        self.global_batch_convert_button.grid(row=0, column=0, columnspan=2, padx=5, pady=2)
        self.global_batch_convert_button.grid_remove()  # 默认隐藏
        
        # 放置进度框架
        self.progress_frame.grid(row=2, column=0, sticky="ew", padx=5, pady=5)
        self.progress_frame.columnconfigure(0, weight=1)  # 进度条占据大部分空间
        
        # 进度条和停止按钮布局
        self.progress_bar.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        self.progress_label.grid(row=0, column=1, sticky="w", padx=2, pady=5)
        self.stop_button.grid(row=0, column=2, sticky="e", padx=5, pady=5)
        
        # 隐藏停止按钮（初始状态）
        self.stop_button.grid_remove()
        
        # 批量转换选项卡布局 - 两列布局
        self.batch_frame.columnconfigure(0, weight=1)
        self.batch_frame.columnconfigure(1, weight=1)
        
        # 输入目录框架
        self.batch_input_frame.grid(row=0, column=0, columnspan=2, sticky="ew", padx=5, pady=5)
        self.batch_input_frame.columnconfigure(0, weight=1)
        self.batch_input_entry.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        self.batch_input_button.grid(row=0, column=1, sticky="e", padx=5, pady=5)
        
        # 输出目录框架
        self.batch_output_frame.grid(row=1, column=0, columnspan=2, sticky="ew", padx=5, pady=5)
        self.batch_output_frame.columnconfigure(0, weight=1)
        self.batch_output_entry.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        self.batch_output_button.grid(row=0, column=1, sticky="e", padx=5, pady=5)
        
        # 左侧：文件格式框架
        self.batch_format_frame.grid(row=2, column=0, sticky="nsew", padx=5, pady=5)
        self.batch_format_frame.columnconfigure(1, weight=1)
        
        # 输入格式
        self.input_format_label.grid(row=0, column=0, sticky="w", padx=5, pady=5)
        self.input_formats_frame.grid(row=0, column=1, sticky="w", padx=5, pady=5)
        
        # 输出格式
        self.output_format_label.grid(row=1, column=0, sticky="w", padx=5, pady=5)
        self.output_format_combo.grid(row=1, column=1, sticky="w", padx=5, pady=5)
        
        # 递归处理选项 - 放到文件格式框架中的第三行
        self.recursive_check.grid(row=2, column=0, columnspan=2, sticky="w", padx=5, pady=5)
        
        # 右侧：转换选项框架
        self.batch_options_frame.grid(row=2, column=1, sticky="nsew", padx=5, pady=5)
        self.batch_options_frame.columnconfigure(1, weight=1)
        
        # 设置批量转换选项
        self._setup_batch_options()
        
        # 日志区域
        self.log_frame.grid(row=3, column=0, sticky="nsew", padx=5, pady=5)
        self.log_frame.columnconfigure(0, weight=1)
        self.log_frame.rowconfigure(0, weight=1)
        self.log_text.grid(row=0, column=0, sticky="nsew")
        self.log_scroll.grid(row=0, column=1, sticky="ns")
        
        # 底部状态栏
        self.status_label.grid(row=4, column=0, sticky="ew", padx=0, pady=0)
    
    def _setup_bindings(self):
        """设置事件绑定"""
        # 选项卡切换事件
        self.notebook.bind("<<NotebookTabChanged>>", self._on_tab_changed)
        
        # 窗口关闭事件
        self.protocol("WM_DELETE_WINDOW", self._on_close)
    
    def _browse_input_file(self, input_var, output_format):
        """浏览输入文件对话框"""
        filetypes = []
        for ext in SUPPORTED_INPUT_FORMATS:
            ext_clean = ext.strip('.')
            filetypes.append((f"{ext_clean.upper()}文件", f"*{ext}"))
        filetypes.append(("所有文件", "*.*"))
        
        filename = filedialog.askopenfilename(
            title="选择视频文件",
            filetypes=filetypes
        )
        if filename:
            input_var.set(filename)
            
            # 如果对应的输出文件未设置，自动设置为相同位置但更改后缀
            output_var = self.format_frames[output_format]["output_var"]
            if not output_var.get():
                output_file = Path(filename).with_suffix(f'.{output_format}')
                output_var.set(str(output_file))
    
    def _browse_output_file(self, output_var, output_format):
        """浏览输出文件对话框"""
        filename = filedialog.asksaveasfilename(
            title=f"保存{output_format.upper()}文件",
            filetypes=[(f"{output_format.upper()}文件", f"*.{output_format}"), ("所有文件", "*.*")],
            defaultextension=f".{output_format}"
        )
        if filename:
            output_var.set(filename)
    
    def _browse_input_dir(self):
        """浏览输入目录对话框"""
        dirname = filedialog.askdirectory(title="选择包含视频文件的目录")
        if dirname:
            self.batch_input_var.set(dirname)
            
            # 如果输出目录未设置，自动设置为相同目录
            if not self.batch_output_var.get():
                self.batch_output_var.set(dirname)
    
    def _browse_output_dir(self):
        """浏览输出目录对话框"""
        dirname = filedialog.askdirectory(title="选择输出目录")
        if dirname:
            self.batch_output_var.set(dirname)
    
    def _on_tab_changed(self, event):
        """选项卡切换事件处理"""
        current_tab = self.notebook.index(self.notebook.select())
        tab_name = self.notebook.tab(current_tab, "text")
        
        # 如果切换到批量转换选项卡，显示主界面的批量转换按钮
        if tab_name == "批量转换":
            self.global_batch_convert_button.grid()
        else:
            self.global_batch_convert_button.grid_remove()
    
    def _start_single_conversion(self, input_var, output_var, output_format):
        """开始单文件转换"""
        if self.converting:
            messagebox.showinfo("提示", "正在进行转换，请等待当前转换完成。")
            return
        
        input_file = input_var.get()
        if not input_file:
            messagebox.showerror("错误", "请选择输入文件。")
            return
        
        output_file = output_var.get()
        
        # 获取该格式界面的编码器变量
        format_data = self.format_frames[output_format]
        video_codec = format_data["format_video_codec_var"].get()
        audio_codec = format_data["format_audio_codec_var"].get()
        video_bitrate = format_data["format_video_bitrate_var"].get()
        audio_bitrate = format_data["format_audio_bitrate_var"].get()
        hw_accel = format_data["format_hw_accel_var"].get()
        speed_preset = format_data["format_speed_preset_var"].get()
        
        # 获取转换选项
        options = {
            "output_format": output_format,
            "video_codec": video_codec,
            "audio_codec": audio_codec,
            "audio_bitrate": audio_bitrate
        }
        
        # 仅在有值时添加视频比特率
        if video_bitrate:
            options["video_bitrate"] = video_bitrate
            
        # 仅在有值时添加硬件加速
        if hw_accel:
            options["hw_accel"] = hw_accel
            
        # 添加速度预设
        options["speed_preset"] = speed_preset
        
        # 启动转换线程
        self._start_conversion_thread(
            task_type="single",
            input_path=input_file,
            output_path=output_file,
            options=options
        )
    
    def _start_batch_conversion(self):
        """开始批量转换"""
        if self.converting:
            messagebox.showinfo("提示", "正在进行转换，请等待当前转换完成。")
            return
        
        input_dir = self.batch_input_var.get()
        if not input_dir:
            messagebox.showerror("错误", "请选择输入目录。")
            return
        
        output_dir = self.batch_output_var.get()
        recursive = self.recursive_var.get()
        output_format = self.output_format_var.get()
        
        # 获取选中的输入格式
        selected_extensions = []
        for fmt, var in self.input_format_vars.items():
            if var.get():
                selected_extensions.append(f'.{fmt}')
        
        if not selected_extensions:
            messagebox.showerror("错误", "请至少选择一种输入文件格式。")
            return
        
        # 根据选择的输出格式设置推荐的编码器
        video_codec = self.video_codec_var.get()
        audio_codec = self.audio_codec_var.get()
        
        # 根据输出格式自动设置推荐编码器
        if output_format.lower() == "mp4":
            if video_codec not in ["libx264", "libx265", "copy"]:
                video_codec = "libx264"
            if audio_codec not in ["aac", "mp3", "copy"]:
                audio_codec = "aac"
        elif output_format.lower() == "avi":
            if video_codec not in ["mpeg4", "msmpeg4", "libxvid", "copy"]:
                video_codec = "mpeg4"
            if audio_codec not in ["mp3", "ac3", "copy"]:
                audio_codec = "mp3"
        elif output_format.lower() == "mkv":
            if video_codec not in ["libx264", "libx265", "copy"]:
                video_codec = "libx264"
            if audio_codec not in ["aac", "ac3", "dts", "copy"]:
                audio_codec = "aac"
        elif output_format.lower() == "mov":
            if video_codec not in ["libx264", "prores", "copy"]:
                video_codec = "libx264"
            if audio_codec not in ["aac", "alac", "pcm_s16le", "copy"]:
                audio_codec = "aac"
        elif output_format.lower() == "webm":
            if video_codec not in ["libvpx-vp9", "libvpx", "copy"]:
                video_codec = "libvpx-vp9"
            if audio_codec not in ["libopus", "libvorbis", "copy"]:
                audio_codec = "libopus"
        
        # 更新界面中的编码器选择，以反映推荐设置
        self.video_codec_var.set(video_codec)
        self.audio_codec_var.set(audio_codec)
        
        # 获取转换选项
        options = {
            "output_format": output_format,
            "video_codec": video_codec,
            "audio_codec": audio_codec,
            "audio_bitrate": self.audio_bitrate_var.get(),
            "file_extensions": selected_extensions,
            "hw_accel": self.hw_accel_var.get() if self.hw_accel_var.get() else None,
            "speed_preset": self.speed_preset_var.get()
        }
        
        # 仅在有值时添加视频比特率
        video_bitrate = self.video_bitrate_var.get()
        if video_bitrate:
            options["video_bitrate"] = video_bitrate
            
        # 仅在有值时添加并行任务数
        max_workers = self.max_workers_var.get()
        if max_workers and max_workers.isdigit():
            options["max_workers"] = int(max_workers)
        
        # 启动转换线程
        self._start_conversion_thread(
            task_type="batch",
            input_path=input_dir,
            output_path=output_dir,
            options=options,
            recursive=recursive
        )
    
    def _start_conversion_thread(self, task_type, input_path, output_path=None, options=None, recursive=False):
        """启动转换线程"""
        self.converting = True
        self._update_status("准备转换...", "processing")
        self._update_buttons_state()
        
        # 停止按钮
        self.stop_button.grid()  # 显示停止按钮
        
        # 清空日志区域
        self.log_text.delete(1.0, tk.END)
        
        # 创建进程引用字典
        self.process_ref = {}
        
        # 创建并启动线程
        self.conversion_thread = threading.Thread(
            target=self._conversion_worker,
            args=(task_type, input_path, output_path, options, recursive),
            daemon=True
        )
        self.conversion_thread.start()
    
    def _conversion_worker(self, task_type, input_path, output_path, options, recursive):
        """转换工作线程"""
        try:
            if task_type == "single":
                self._append_log(f"开始转换: {input_path} -> {output_path}")
                
                # 进度回调函数
                def progress_callback(progress):
                    # 更新进度条和状态
                    self.queue.put(("progress", progress))
                
                # 启动转换
                success = convert_video(
                    input_path,
                    output_path,
                    progress_callback=progress_callback,
                    process_ref=self.process_ref,
                    **options
                )
                
                if success:
                    self.queue.put(("status", "转换成功!", "success"))
                else:
                    self.queue.put(("status", "转换失败!", "error"))
                
            elif task_type == "batch":
                self._append_log(f"开始批量转换: {input_path} -> {output_path}")
                self._append_log(f"输出格式: {options.get('output_format', 'mp4')}")
                
                if 'max_workers' in options and options['max_workers']:
                    self._append_log(f"使用 {options['max_workers']} 个工作进程进行并行转换")
                
                if options.get('hw_accel'):
                    self._append_log(f"使用硬件加速: {options['hw_accel']}")
                
                # 创建进度回调函数
                def progress_callback(progress):
                    # 更新进度条和状态
                    self.queue.put(("progress", progress))
                    
                    # 每10%更新一次状态
                    if int(progress * 100) % 10 == 0:
                        self.queue.put(("status", f"批量转换进度: {int(progress * 100)}%", "processing"))
                
                # 将process_ref从options中移除，因为batch_convert不支持此参数
                batch_options = options.copy()
                if 'process_ref' in batch_options:
                    del batch_options['process_ref']
                
                # 启动批量转换
                successful_count, total_count = batch_convert(
                    input_path,
                    output_path,
                    recursive=recursive,
                    progress_callback=progress_callback,
                    **batch_options
                )
                
                # 更新状态
                if successful_count == total_count and total_count > 0:
                    self.queue.put(("status", f"批量转换完成! 成功: {successful_count}/{total_count}", "success"))
                elif successful_count > 0:
                    self.queue.put(("status", f"部分转换成功! 成功: {successful_count}/{total_count}", "warning"))
                else:
                    self.queue.put(("status", f"转换失败! 成功: {successful_count}/{total_count}", "error"))
        
        except Exception as e:
            self._append_log(f"转换过程出错: {str(e)}")
            self.queue.put(("status", "转换过程出错!", "error"))
        
        finally:
            # 转换完成，更新状态
            self.converting = False
            self.queue.put(("converting_done",))
    
    def _process_queue(self):
        """处理消息队列中的消息"""
        try:
            while True:
                item = self.queue.get_nowait()
                
                # 确保item是元组并至少有一个元素
                if not isinstance(item, tuple) or len(item) < 1:
                    continue
                
                message_type = item[0]
                
                if message_type == "log":
                    if len(item) > 1:
                        self._append_log(item[1])
                elif message_type == "progress":
                    if len(item) > 1:
                        progress = item[1]
                        # 确保进度值在0-1之间
                        progress = max(0, min(1, progress))
                        # 更新进度条 - 使用百分比值(0-100)
                        progress_percent = progress * 100
                        self.progress_var.set(progress_percent)
                        # 更新文本标签 - 显示整数百分比
                        percentage = int(progress_percent)
                        self.progress_label.config(text=f"{percentage}%")
                elif message_type == "status":
                    if len(item) > 2:
                        message, status_type = item[1], item[2]
                        self._update_status(message, status_type)
                elif message_type == "converting_done":
                    self._update_buttons_state()
                elif message_type == "enable":
                    # 处理启用按钮的消息
                    pass
                
        except queue.Empty:
            pass
        
        # 继续处理队列
        self.after(100, self._process_queue)
    
    def _append_log(self, message):
        """向日志区域添加消息"""
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)
    
    def _stop_conversion(self):
        """停止转换进程"""
        if not self.converting:
            return
            
        if messagebox.askyesno("确认", "确定要停止当前转换任务吗？"):
            self._append_log("用户中止转换")
            self.status_var.set("转换已中止")
            
            # 标记正在转换的标志为False
            self.converting = False
            
            # 终止转换进程
            if hasattr(self, 'process_ref') and self.process_ref and 'process' in self.process_ref:
                try:
                    process = self.process_ref['process']
                    if process:
                        # 先强制终止子进程
                        import signal
                        if sys.platform == 'win32':
                            import subprocess
                            subprocess.run(['taskkill', '/F', '/T', '/PID', str(process.pid)], 
                                        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                        else:
                            os.killpg(os.getpgid(process.pid), signal.SIGTERM)
                        process.terminate()
                except Exception as e:
                    self._append_log(f"停止转换时出错: {str(e)}")
                finally:
                    self.process_ref = {}
            
            # 启用所有转换按钮
            for _, frame_data in self.format_frames.items():
                frame_data["convert_button"].state(['!disabled'])
            self.batch_convert_button.state(['!disabled'])
            
            # 隐藏所有停止按钮
            self.stop_button.grid_remove()
            
            # 重置进度条
            self.progress_var.set(0)
            self.progress_label.config(text="0%")
            
            # 添加到队列以确保UI更新
            self.queue.put(("enable",))
    
    def _on_close(self):
        """窗口关闭处理"""
        if self.converting:
            if messagebox.askyesno("确认", "正在进行转换，确定要退出吗？"):
                # 终止转换进程
                if hasattr(self, 'process_ref') and self.process_ref:
                    try:
                        self.process_ref.terminate()
                    except:
                        pass
                self.destroy()
        else:
            self.destroy()

    def _create_tooltip(self, widget, text):
        """创建工具提示"""
        tooltip = ToolTip(widget, text)
        
        def enter(event):
            tooltip.showtip()
            
        def leave(event):
            tooltip.hidetip()
            
        widget.bind('<Enter>', enter)
        widget.bind('<Leave>', leave)
        
    def _setup_batch_options(self):
        """设置批量转换选项"""
        # 视频编码器
        self.video_codec_label = ttk.Label(self.batch_options_frame, text="视频编码器:")
        self.video_codec_combo = ttk.Combobox(self.batch_options_frame, textvariable=self.video_codec_var, width=15)
        self.video_codec_combo['values'] = ('libx264', 'libx265', 'copy')
        self.video_codec_combo.state(['readonly'])
        
        # 视频编码器说明
        video_codec_help = ttk.Label(self.batch_options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(video_codec_help, 
                           "视频编码器选项说明:\n"
                           "libx264: H.264编码，兼容性最好，推荐使用\n"
                           "libx265: H.265/HEVC编码，更高压缩率但兼容性较差\n"
                           "copy: 直接复制视频流，不重新编码，速度最快")
        
        # 音频编码器
        self.audio_codec_label = ttk.Label(self.batch_options_frame, text="音频编码器:")
        self.audio_codec_combo = ttk.Combobox(self.batch_options_frame, textvariable=self.audio_codec_var, width=15)
        self.audio_codec_combo['values'] = ('aac', 'mp3', 'copy')
        self.audio_codec_combo.state(['readonly'])
        
        # 音频编码器说明
        audio_codec_help = ttk.Label(self.batch_options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(audio_codec_help, 
                           "音频编码器选项说明:\n"
                           "aac: 高质量音频编码，适用于大多数场景，推荐使用\n"
                           "mp3: 常用音频格式，兼容性好\n"
                           "copy: 直接复制音频流，不重新编码，速度最快")
        
        # 视频比特率
        self.video_bitrate_label = ttk.Label(self.batch_options_frame, text="视频比特率:")
        self.video_bitrate_entry = ttk.Entry(self.batch_options_frame, textvariable=self.video_bitrate_var, width=15)
        
        # 视频比特率说明
        video_bitrate_help = ttk.Label(self.batch_options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(video_bitrate_help, 
                           "视频比特率建议值:\n"
                           "720p: 2000k-4000k\n"
                           "1080p: 4000k-8000k\n"
                           "4K: 15000k-30000k\n"
                           "留空则使用质量控制模式(CRF)")
        
        # 音频比特率
        self.audio_bitrate_label = ttk.Label(self.batch_options_frame, text="音频比特率:")
        self.audio_bitrate_entry = ttk.Entry(self.batch_options_frame, textvariable=self.audio_bitrate_var, width=15)
        
        # 音频比特率说明
        audio_bitrate_help = ttk.Label(self.batch_options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(audio_bitrate_help, 
                           "音频比特率建议值:\n"
                           "普通质量: 128k\n"
                           "标准质量: 192k (默认)\n"
                           "高质量: 256k-320k")
        
        # 硬件加速选项
        self.hw_accel_label = ttk.Label(self.batch_options_frame, text="硬件加速:")
        self.hw_accel_combo = ttk.Combobox(self.batch_options_frame, textvariable=self.hw_accel_var, width=15)
        
        # 设置可用的硬件加速选项
        hw_accel_options = ['']  # 空选项表示不使用硬件加速
        available_hw = [k for k, v in self.available_hw_accel.items() if v]
        if available_hw:
            hw_accel_options.extend(available_hw)
            self._append_log(f"检测到可用的硬件加速选项: {', '.join(available_hw)}")
        else:
            self._append_log("未检测到支持的硬件加速选项")
            
        self.hw_accel_combo['values'] = hw_accel_options
        self.hw_accel_combo.state(['readonly'])
        
        # 硬件加速说明
        hw_accel_help = ttk.Label(self.batch_options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(hw_accel_help, 
                          "硬件加速选项说明:\n"
                          "空白: 不使用硬件加速\n"
                          "nvidia: 使用NVIDIA GPU加速\n"
                          "amd: 使用AMD GPU加速\n"
                          "intel: 使用Intel Quick Sync加速\n"
                          "apple: 使用Apple VideoToolbox加速\n\n"
                          "启用硬件加速可以显著提高转换速度，但可能影响视频质量")
        
        # 速度预设
        self.speed_preset_label = ttk.Label(self.batch_options_frame, text="速度预设:")
        self.speed_preset_combo = ttk.Combobox(self.batch_options_frame, textvariable=self.speed_preset_var, width=15)
        self.speed_preset_combo['values'] = ('ultrafast', 'veryfast', 'fast', 'medium', 'slow', 'veryslow')
        self.speed_preset_combo.state(['readonly'])
        
        # 速度预设说明
        speed_preset_help = ttk.Label(self.batch_options_frame, text="?", foreground="blue", cursor="hand2")
        
        # 从webm_to_mp4模块获取速度预设描述
        try:
            from webm_to_mp4 import SPEED_PRESET_DESCRIPTIONS
            preset_desc = "\n".join([f"{preset}: {desc}" for preset, desc in SPEED_PRESET_DESCRIPTIONS.items()])
        except ImportError:
            preset_desc = (
                "ultrafast: 极速转换，质量最低\n"
                "veryfast: 非常快，质量较低\n"
                "fast: 快速，质量较好\n"
                "medium: 中等速度和质量(默认)\n"
                "slow: 慢速，高质量\n"
                "veryslow: 非常慢，最高质量"
            )
            
        self._create_tooltip(speed_preset_help, f"速度预设选项说明:\n{preset_desc}")
        
        # 并行任务数
        self.max_workers_label = ttk.Label(self.batch_options_frame, text="并行任务数:")
        self.max_workers_entry = ttk.Entry(self.batch_options_frame, textvariable=self.max_workers_var, width=15)
        
        # 获取CPU核心数并设置默认值
        import multiprocessing
        cpu_count = multiprocessing.cpu_count()
        self.max_workers_var.set(str(min(cpu_count, 4)))  # 默认使用CPU核心数，但最多4个
        
        # 并行任务数说明
        max_workers_help = ttk.Label(self.batch_options_frame, text="?", foreground="blue", cursor="hand2")
        self._create_tooltip(max_workers_help, 
                           f"并行任务数说明:\n"
                           f"设置同时转换的视频文件数量\n"
                           f"留空则自动设置为CPU核心数\n"
                           f"系统检测到 {cpu_count} 个CPU核心\n"
                           f"推荐值: 2-{cpu_count}")
        
        # 布局 - 调整为更紧凑的布局
        # 第一行：视频编码器和音频编码器
        self.video_codec_label.grid(row=0, column=0, sticky="w", padx=5, pady=2)
        self.video_codec_combo.grid(row=0, column=1, sticky="w", padx=5, pady=2)
        video_codec_help.grid(row=0, column=1, sticky="e", padx=(0, 10), pady=2)
        
        self.audio_codec_label.grid(row=1, column=0, sticky="w", padx=5, pady=2)
        self.audio_codec_combo.grid(row=1, column=1, sticky="w", padx=5, pady=2)
        audio_codec_help.grid(row=1, column=1, sticky="e", padx=(0, 10), pady=2)
        
        # 第二行：视频比特率和音频比特率
        self.video_bitrate_label.grid(row=2, column=0, sticky="w", padx=5, pady=2)
        self.video_bitrate_entry.grid(row=2, column=1, sticky="w", padx=5, pady=2)
        video_bitrate_help.grid(row=2, column=1, sticky="e", padx=(0, 10), pady=2)
        
        self.audio_bitrate_label.grid(row=3, column=0, sticky="w", padx=5, pady=2)
        self.audio_bitrate_entry.grid(row=3, column=1, sticky="w", padx=5, pady=2)
        audio_bitrate_help.grid(row=3, column=1, sticky="e", padx=(0, 10), pady=2)
        
        # 第三行：硬件加速和速度预设
        self.hw_accel_label.grid(row=4, column=0, sticky="w", padx=5, pady=2)
        self.hw_accel_combo.grid(row=4, column=1, sticky="w", padx=5, pady=2)
        hw_accel_help.grid(row=4, column=1, sticky="e", padx=(0, 10), pady=2)
        
        self.speed_preset_label.grid(row=5, column=0, sticky="w", padx=5, pady=2)
        self.speed_preset_combo.grid(row=5, column=1, sticky="w", padx=5, pady=2)
        speed_preset_help.grid(row=5, column=1, sticky="e", padx=(0, 10), pady=2)
        
        # 第四行：并行任务数
        self.max_workers_label.grid(row=6, column=0, sticky="w", padx=5, pady=2)
        self.max_workers_entry.grid(row=6, column=1, sticky="w", padx=5, pady=2)
        max_workers_help.grid(row=6, column=1, sticky="e", padx=(0, 10), pady=2)

    def _detect_hw_accel(self):
        """检测系统支持的硬件加速选项"""
        try:
            from webm_to_mp4 import detect_hardware_acceleration
            return detect_hardware_acceleration()
        except Exception as e:
            self._append_log(f"硬件加速检测失败: {str(e)}")
            return {'nvidia': False, 'amd': False, 'intel': False, 'apple': False}

    def _update_status(self, message, status_type="normal"):
        """更新状态栏信息"""
        self.status_var.set(message)
        
        # 设置状态颜色
        if status_type == "success":
            self.status_label.config(foreground="#2ecc71")  # 绿色
        elif status_type == "error":
            self.status_label.config(foreground="#e74c3c")  # 红色
        elif status_type == "warning":
            self.status_label.config(foreground="#e67e22")  # 橙色
        elif status_type == "processing":
            self.status_label.config(foreground="#3498db")  # 蓝色
        else:
            self.status_label.config(foreground="#555555")  # 默认灰色

    def _update_buttons_state(self):
        """根据转换状态更新按钮状态"""
        if self.converting:
            # 禁用所有转换按钮
            for output_format, frame_data in self.format_frames.items():
                frame_data["convert_button"].state(['disabled'])
            
            # 禁用批量转换按钮
            self.batch_convert_button.state(['disabled'])
            
            # 重置进度条和标签
            self.progress_var.set(0)
            self.progress_label.config(text="0%")
        else:
            # 启用所有转换按钮
            for output_format, frame_data in self.format_frames.items():
                frame_data["convert_button"].state(['!disabled'])
            
            # 启用批量转换按钮
            self.batch_convert_button.state(['!disabled'])
            
            # 清除停止按钮（如果存在）
            if hasattr(self, 'stop_button') and self.stop_button:
                self.stop_button.grid_remove()

# 工具提示类
class ToolTip:
    def __init__(self, widget, text):
        self.widget = widget
        self.text = text
        self.tip_window = None
        
    def showtip(self):
        """显示工具提示"""
        if self.tip_window or not self.text:
            return
            
        x, y, _, _ = self.widget.bbox("insert")
        x += self.widget.winfo_rootx() + 25
        y += self.widget.winfo_rooty() + 25
        
        self.tip_window = tw = tk.Toplevel(self.widget)
        tw.wm_overrideredirect(True)
        tw.wm_geometry(f"+{x}+{y}")
        
        label = tk.Label(tw, text=self.text, background="#FFFFAA", foreground="#000000",
                         relief=tk.SOLID, borderwidth=1, justify=tk.LEFT,
                         font=("微软雅黑", 9), padx=5, pady=5)
        label.pack()
        
    def hidetip(self):
        """隐藏工具提示"""
        tw = self.tip_window
        self.tip_window = None
        if tw:
            tw.destroy()

def main():
    """主程序入口"""
    app = VideoConverterGUI()
    app.mainloop()

if __name__ == "__main__":
    main() 